package com.example.myspringframework.context.annotation;

import cn.hutool.core.util.StrUtil;
import com.example.myspringframework.beans.factory.config.BeanDefinition;
import com.example.myspringframework.beans.factory.config.BeanDefinitionRegistry;
import com.example.myspringframework.stereotype.Component;

import java.util.Set;

/**
 * 实现包扫描的功能
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
    private final BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public void doScan(String... basePackages) {
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                // 解析scope注解
                String scope = this.resolveBeanScope(candidate);
                if (StrUtil.isNotEmpty(scope)) {
                    candidate.setScope(scope);
                }
                // 解析beanName
                String beanName = this.determineBeanName(candidate);
                this.registry.registerBeanDefinition(beanName, candidate);
            }
        }
        // 注册解析注解相关的BeanPostProcessor
        this.registry.registerBeanDefinition("autowiredAnnotationBeanPostProcessor",new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
    }

    // 解析Scope注解
    private String resolveBeanScope(BeanDefinition beanDefinition){
        Class<?> beanClass = beanDefinition.getBeanClass();
        Scope scope = beanClass.getAnnotation(Scope.class);
        if(scope != null){
            return scope.value();
        }
        return StrUtil.EMPTY;
    }

    // 解析bean的名称
    private String determineBeanName(BeanDefinition beanDefinition){
        Class<?> beanClass = beanDefinition.getBeanClass();
        Component component = beanClass.getAnnotation(Component.class);
        String value = component.value();
        if(StrUtil.isEmpty(value)){
            value = StrUtil.lowerFirst(beanClass.getSimpleName());
        }
        return value;
    }
}
